package com.yunmasoft.service.pay.wexin;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

public class Notify extends WxpayResponseBase {
    // CONSTANTS
    //protected Boolean validity = null;
    public static final String KEY_APPID = "appid";
    public static final String KEY_MCH_ID = "mch_id";
    public static final String KEY_OPENID = "openid";
    public static final String KEY_TRANSACTION_ID = "transaction_id";
    public static final String KEY_OUT_TRADE_NO = "out_trade_no";
    public static final String KEY_TOTAL_FEE = "total_fee";
    public static final String KEY_CASH_FEE = "cash_fee";
    public static final String KEY_COUPON_FEE = "coupon_fee";
    public static final String KEY_COUPON_COUNT = "coupon_count";
    public static final String KEY_TIME_END = "time_end";

    public static List<String> KEYS_PARAM_NAME_TEMPLATE = Arrays.asList(
            "appid",
            "attach",
            "bank_type",
            "cash_fee",
            "cash_fee_type",
            "coupon_count",
            "coupon_fee",
            "coupon_fee_$0",
            "coupon_id_$0",
            "device_info",
            "err_code",
            "err_code_des",
            "fee_type",
            "is_subscribe",
            "mch_id",
            "nonce_str",
            SnsOAuthAccessTokenResponse.KEY_OPENID,
            "out_trade_no",
            "result_code",
            "return_code",
            "return_msg",
            "sign",
            "time_end",
            "total_fee",
            "trade_type",
            "transaction_id"
    );

    public List<String> keysParamName = null;

    // CONSTRUCT

    /**
     * @deprecated use Notify(String notifyXml) instead.
     */
    public Notify(WxpayResponseBase resp) {
        this(resp.respString, resp.respProp);

        return;
    }

    /**
     * @deprecated use Notify(String notifyXml) instead.
     */
    public Notify(String respString, Properties respProp) {
        super(respString, respProp);

        return;
    }

    /**
     * @deprecated since 0.4.5.
     */
    public Notify(String notifyXml) {
        super(notifyXml);

        return;
    }

    public Notify(InputStream notifyXml)
            throws IOException {
        super(notifyXml);

        return;
    }

    protected List<String> getKeysParamName() {
        return getKeysParamName(this.keysParamName);
    }

    //VERIFY
    public List<String> getKeysParamName(List<String> keysParamName) {
        if (keysParamName != null)
            return (keysParamName);

        // else
        Integer couponCount = this.getCouponCount();

        List<String> l = new ArrayList<String>();
        for (String k : KEYS_PARAM_NAME_TEMPLATE) {
            if (k.contains("$"))
                l.addAll(materializeParamNames(k, 0, couponCount));
            else
                l.add(k);
        }

        keysParamName = l;

        return keysParamName;
    }

    @Override
    protected boolean verifySign(Properties conf)
            throws UnsupportedEncodingException {
        return (
                super.verifySign(
                        this.getKeysParamName(),
                        conf
                )
        );
    }

    // PROPERTY
    // ID
    public String getOpenid() {
        return (
                super.getProperty(KEY_OPENID)
        );
    }

    public String getOutTradeNo() {
        return (
                super.getProperty(KEY_OUT_TRADE_NO)
        );
    }

    public String getTransactionId() {
        return (
                super.getProperty(KEY_TRANSACTION_ID)
        );
    }

    // TIME
    public Date getTimeEnd() {
        return (
                super.getDateProperty(KEY_TIME_END)
        );
    }

    // FEE
    public Integer getTotalFee() {
        return (
                super.getIntProperty(KEY_TOTAL_FEE)
        );
    }

    public Integer getTotalFeeFen() {
        return (
                this.getTotalFee()
        );
    }

    public Double getTotalFeeYuan() {
        Integer fen = this.getTotalFee();
        return (
                fen != null ? (fen.doubleValue() / 100.0) : null
        );
    }

    public Integer getCashFee() {
        return (
                super.getIntProperty(KEY_CASH_FEE)
        );
    }

    public Integer getCashFeeFen() {
        return (
                this.getCashFee()
        );
    }

    public Double getCashFeeYuan() {
        Integer fen = this.getCashFee();
        return (
                fen != null ? (fen.doubleValue() / 100.0) : null
        );
    }

    public Integer getCouponFee() {
        return (
                super.getIntProperty(KEY_COUPON_FEE)
        );
    }

    public Integer getCouponFeeFen() {
        return (
                this.getCouponFee()
        );
    }

    public Double getCouponFeeYuan() {
        Integer fen = this.getCouponFee();
        return (
                fen != null ? (fen.doubleValue() / 100.0) : null
        );
    }

    // COUPON
    public Integer getCouponCount() {
        return (
                this.getIntProperty(KEY_COUPON_COUNT)
        );
    }
}
